
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/proc_fs.h>

#define MAJOR_NUM 123 
#define MINOR_NUM 0
 
MODULE_AUTHOR("mdy");
MODULE_DESCRIPTION("proc file system demo");
MODULE_LICENSE("GPL");


#define bufSize 128
static char kernel_buf[bufSize] = {"Empty\n"};

ssize_t proc_demo_read(struct file *file, char __user *ubuf,size_t count, loff_t *ppos)
{
    int len = strlen(kernel_buf);
    printk("proc read, len = %d, count = %lu, *ppos = %lld\n", len, count, *ppos);

    if(*ppos > 0 || count < bufSize)
        return 0;
    if(copy_to_user(ubuf, kernel_buf, len))
        return -EFAULT;

    *ppos = len;

    return len;
}

static ssize_t proc_demo_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
{
    printk("proc write, count = %lu, *ppos = %lld\n", count, *ppos);

    if(*ppos > 0 || count > bufSize)
            return -EFAULT;
    
    if(copy_from_user(kernel_buf,ubuf,count))
            return -EFAULT;

    printk("the last character = %d\n", (int)kernel_buf[count - 1]);
    kernel_buf[count] = '\0';
    *ppos = count;

    return count;
}

static const struct file_operations proc_demo_fops = {
    .owner      = THIS_MODULE,
    .read       = proc_demo_read,
    .write      = proc_demo_write,
};

static struct proc_dir_entry *ent;
static int __init proc_mod_init(void)
{
    ent = proc_create("proc_demo", 0666, NULL, &proc_demo_fops);
    printk(KERN_ALERT "proc demo create...\n");
    return 0;
}

static void __exit proc_mod_exit(void)
{
    proc_remove(ent);
    printk(KERN_ALERT "proc demo remove...\n");
}
 
module_init(proc_mod_init);
module_exit(proc_mod_exit);


